import logging
import json
import os
import re

import yaml
from typing import Any
import requests
from base64 import b64encode
from cryptography.hazmat.primitives.ciphers import Cipher, algorithms, modes
from cryptography.hazmat.primitives import padding
from cryptography.hazmat.backends import default_backend
from base64 import b64decode

# 获取当前工作目录
base_dir = os.path.abspath(os.path.dirname(__file__))  # 获取当前脚本所在目录
parent_dir = os.path.dirname(base_dir)  # 获取上一层目录
log_file_path = os.path.join(parent_dir, 'log', 'apiSecurity.log')  # 组合成绝对路径

# 设置日志配置
logger = logging.getLogger()
logger.setLevel(logging.INFO)

# 创建一个输出到文件的handler
file_handler = logging.FileHandler(log_file_path, mode='w')
file_handler.setLevel(logging.INFO)
file_handler.setFormatter(logging.Formatter('%(asctime)s %(levelname)s:%(message)s', datefmt='%Y-%m-%d %H:%M:%S'))

# 创建一个输出到控制台的handler
console_handler = logging.StreamHandler()
console_handler.setLevel(logging.INFO)
console_handler.setFormatter(logging.Formatter('%(asctime)s %(levelname)s:%(message)s', datefmt='%Y-%m-%d %H:%M:%S'))

# 将handler添加到logger
logger.addHandler(file_handler)
logger.addHandler(console_handler)


def read_yaml(yaml_file_path: str) -> Any:
    yaml_file_path = "/config/config.yaml"
    """
    参数:
    - yaml_file_path: YAML 文件的路径字符串。
    返回值:
    - 返回解析后的 YAML 文件内容。
    """
    try:
        with open(yaml_file_path, 'r') as file:
            return yaml.safe_load(file)
    except FileNotFoundError:
        logging.info(f"错误：未找到文件 {yaml_file_path}")
        return None
    except yaml.YAMLError as exc:
        logging.info(f"错误：解析 YAML 文件时发生错误 - {exc}")
        return None


def extract_names_from_yaml(yaml_file_path, names_set):
    # 打开并读取 YAML 文件
    with open(yaml_file_path, 'r') as file:
        data = yaml.safe_load(file)

        # 定义一个递归函数来遍历数据
        def extract_names(obj):
            if isinstance(obj, dict):  # 如果条目是字典类型
                for key, value in obj.items():
                    if key == 'name':  # 检查键是否为 'name'
                        names_set.add(value)  # 添加到集合中
                    else:
                        extract_names(value)  # 递归搜索
            elif isinstance(obj, list):  # 如果条目是列表类型
                for item in obj:
                    extract_names(item)  # 对列表中每个条目递归搜索

        # 开始遍历 YAML 数据
        extract_names(data)


def check_target_project(env, mock_project):
    with open('data/config/token.yml', 'r') as f:
        config = yaml.safe_load(f)
    with open('data/config/config.yaml', 'r') as f2:
        url = yaml.safe_load(f2)

    # 获取配置参数
    url = url['environments'][env]['host'] + url['environments'][env]['check_target_project_uri']
    token = config['token']
    headers = {'Content-Type': 'application/json', 'version': '2.0', 'Authorization': token}
    query_params = {
        'page': '1',
        'size': '10',
        'searchKey': mock_project
    }
    payload = {
    }
    data = json.dumps(payload)
    try:
        # 发送 GET 请求
        response = requests.get(url, data=data, headers=headers, params=query_params)

        # 检查响应状态
        response.raise_for_status()  # 如果响应状态码不是 200，抛出异常

        # 解析 JSON 响应
        response_data = response.json()
        # print(response_data)

        # 提取 project_id
        project_id = response_data['data']['list'][0]['id']

        if project_id:
            # print(f"提取到的 project_id: {project_id}")

            # 保存 project_id 到文件
            with open('data/config/project_id.txt', 'w') as id_file:
                id_file.write(project_id)
            logging.info("成功----已提取到Mock项目ID: %s", project_id)
        else:
            logging.warning("失败----未能在响应中找到 project_id")

    except requests.exceptions.RequestException as e:
        logging.error("失败----请求失败: %s", e)
    except json.JSONDecodeError:
        logging.error("失败----解析 JSON 响应失败")


def check_deploy_env(env, deploy_name):
    with open('data/config/token.yml', 'r') as f:
        config = yaml.safe_load(f)
    with open('data/config/config.yaml', 'r') as f2:
        url = yaml.safe_load(f2)

    url = url['environments'][env]['host'] + url['environments'][env]['check_deploy_env']
    token = config['token']
    headers = {'Content-Type': 'application/json', 'version': '2.0', 'Authorization': token}
    query_params = {
        'page': '1',
        'size': '10',
        'searchKey': deploy_name
    }
    payload = {
    }
    data = json.dumps(payload)
    try:
        # 发送 GET 请求
        response = requests.get(url, data=data, headers=headers, params=query_params)

        # 检查响应状态
        response.raise_for_status()  # 如果响应状态码不是 200，抛出异常

        # 解析 JSON 响应
        response_data = response.json()
        # print(response_data)

        # 提取 deploy_id
        deploy_id = response_data['data']['list'][0]['id']

        if deploy_id:
            # print(f"提取到的 deploy_id: {deploy_id}")

            # 保存 deploy_id 到文件
            with open('data/config/deploy_id.txt', 'w') as id_file:
                id_file.write(deploy_id)
            logging.info("成功----已提取到部署环境ID: %s", deploy_id)
        else:
            logging.warning("失败----未能在响应中找到 deploy_id")

    except requests.exceptions.RequestException as e:
        logging.error("失败----请求失败: %s", e)
    except json.JSONDecodeError:
        logging.error("失败----解析 JSON 响应失败")


def check_directory(env):
    with open('data/config/token.yml', 'r') as f:
        config = yaml.safe_load(f)
    with open('data/config/config.yaml', 'r') as f2:
        url = yaml.safe_load(f2)
    with open('data/config/project_id.txt', 'r') as f3:
        project_id = f3.read().strip()

    url = url['environments'][env]['host'] + url['environments'][env]['check_directory1'] + project_id + \
          url['environments'][env]['check_directory2']
    token = config['token']
    headers = {'Content-Type': 'application/json', 'version': '2.0', 'Authorization': token, 'Tenantid': project_id}
    query_params = {
    }
    payload = {
    }
    data = json.dumps(payload)
    try:
        # 发送 GET 请求
        response = requests.get(url, data=data, headers=headers, params=query_params)

        # 检查响应状态
        response.raise_for_status()  # 如果响应状态码不是 200，抛出异常

        # 解析 JSON 响应
        response_data = response.json()
        # print(response_data)

        # 提取 directory_id
        directory_id = response_data['data'][0]['id']

        if directory_id:
            # print(f"提取到的 deploy_id: {directory_id}")

            # 保存 deploy_id 到文件
            with open('data/config/directory_id.txt', 'w') as id_file:
                id_file.write(directory_id)
            logging.info("成功----已提取到目录idID: %s", directory_id)
        else:
            logging.warning("失败----未能在响应中找到 directory_id")

    except requests.exceptions.RequestException as e:
        logging.error("失败----请求失败: %s", e)
    except json.JSONDecodeError:
        logging.error("失败----解析 JSON 响应失败")


def check_service_id(env, mock_service_name):
    with open('data/config/token.yml', 'r') as f:
        config = yaml.safe_load(f)
    with open('data/config/config.yaml', 'r') as f2:
        url = yaml.safe_load(f2)
    with open('data/config/project_id.txt', 'r') as f3:
        project_id = f3.read().strip()

    url = url['environments'][env]['host'] + url['environments'][env]['check_service_id']
    token = config['token']
    headers = {'Content-Type': 'application/json', 'version': '2.0', 'Authorization': token, 'Tenantid': project_id}
    query_params = {
        'page': '1',
        'size': '10',
        'filter': '{"serviceType":["HTTP"]}',
        'searchKey': mock_service_name
    }
    payload = {
    }
    data = json.dumps(payload)
    try:
        # 发送 GET 请求
        response = requests.get(url, data=data, headers=headers, params=query_params)

        # 检查响应状态
        response.raise_for_status()  # 如果响应状态码不是 200，抛出异常

        # 解析 JSON 响应
        response_data = response.json()
        # print(response_data)

        # 提取 directory_id
        service_id = response_data['data']['list'][0]['id']

        if service_id:
            # print(f"提取到的 deploy_id: {directory_id}")

            # 保存 deploy_id 到文件
            with open('data/config/service_id.txt', 'w') as id_file:
                id_file.write(service_id)
            logging.info("成功----已提取到后端服务ID: %s", service_id)
        else:
            logging.warning("失败----未能在响应中找到 service_id")

    except requests.exceptions.RequestException as e:
        logging.error("失败----请求失败: %s", e)
    except json.JSONDecodeError:
        logging.error("失败----解析 JSON 响应失败")


def process_input(mockConfig):
    # 输出处理
    mockConfigNew = json.dumps(json.loads(mockConfig), ensure_ascii=False)
    # print(mockConfigNew)
    return mockConfigNew


def process_input3(test_url, test_config_str, api_id):
    # 替换 api 的值
    pattern_api = r'"api":"[^"]+"'
    replacement_api = f'"api":"{api_id}"'
    modified_string = re.sub(pattern_api, replacement_api, test_config_str)

    # 替换 url 的值
    pattern_url = r'"url":"[^"]+"'  # 确保匹配到完整的 URL 值
    replacement_url = f'"url":"{test_url}"'
    modified_string = re.sub(pattern_url, replacement_url, modified_string)  # 使用更新后的 modified_string

    return modified_string


def process_input4(test_url, test_config_str, api_id):
    # 解析原始 JSON 字符串
    config_data = json.loads(test_config_str)

    # 替换 api 的值
    config_data["api"] = api_id

    # 替换 detail 中的 url 值
    detail_data = json.loads(config_data["detail"])
    detail_data["resquest"]["url"] = test_url

    # 将修改后的 detail 数据写回
    config_data["detail"] = json.dumps(detail_data)

    # 返回修改后的 JSON 字符串
    return json.dumps(config_data, ensure_ascii=False)


# 测试
test_url = "http://example.com"
test_config_str = '{"api":"353d2020-9a83-478d-9a90-460e168a037d","detail":"{\\"resquestParams\\":{\\"header\\":[{\\"name\\":\\"X-App-Id\\",\\"value\\":\\"1\\"},{\\"name\\":\\"X-Timestamp\\",\\"value\\":\\"2\\"},{\\"name\\":\\"X-Sequence-No\\",\\"value\\":\\"3\\"},{\\"name\\":\\"X-Signature\\",\\"value\\":\\"4\\"},{\\"name\\":\\"Content-Type\\",\\"value\\":\\"application/json\\"}],\\"query\\":[{\\"name\\":\\"2\\",\\"value\\":\\"2\\"}],\\"body\\":\\"{\\\\\\"1\\\\\\":\\\\\\"1\\\\\\"}\\"},\\"resquest\\":{\\"method\\":\\"POST\\",\\"url\\":\\"http://192.168.6.57:8000/IndexTest/1/anything\\"}}"}'
api_id = "new-api-id"

modified_str = process_input3(test_url, test_config_str, api_id)
print(modified_str)



def check_release_id(env, apiName):
    with open('data/config/token.yml', 'r') as f:
        config = yaml.safe_load(f)
    with open('data/config/config.yaml', 'r') as f2:
        url = yaml.safe_load(f2)
    with open('data/config/project_id.txt', 'r') as f3:
        project_id = f3.read().strip()

    url = url['environments'][env]['host'] + url['environments'][env]['check_release_id']
    token = config['token']
    headers = {'Content-Type': 'application/json', 'version': '2.0', 'Authorization': token, 'Tenantid': project_id}
    query_params = {
        'page': '1',
        'size': '10',
        'filter': '{}',
        'searchKey': apiName
    }
    payload = {
    }
    data = json.dumps(payload)
    try:
        # 发送 GET 请求
        response = requests.get(url, data=data, headers=headers, params=query_params)

        # 检查响应状态
        response.raise_for_status()  # 如果响应状态码不是 200，抛出异常

        # 解析 JSON 响应
        response_data = response.json()
        # print(response_data)

        # 提取 directory_id
        release_id = response_data['data']['list'][0]['id']

        if release_id:
            # print(f"提取到的 deploy_id: {directory_id}")

            # 保存 deploy_id 到文件
            # with open('data/config/release_id.txt', 'w') as id_file:
            #     id_file.write(release_id)
            logging.info("成功----已提取到APIreleaseID: %s", release_id)
            return release_id
        else:
            logging.warning("失败----未能在响应中找到 release_id")

    except requests.exceptions.RequestException as e:
        logging.error("失败----请求失败: %s", e)
    except json.JSONDecodeError:
        logging.error("失败----解析 JSON 响应失败")


# AES 加密方法
def encrypt_with_aes(message, key):
    try:
        iv = b"1234567890123456"
        key = key.encode("utf-8")
        message = message.encode("utf-8")

        cipher = Cipher(algorithms.AES(key), modes.CBC(iv), backend=default_backend())
        encryptor = cipher.encryptor()

        # 对消息进行填充以适应 AES 块大小
        padder = padding.PKCS7(algorithms.AES.block_size).padder()
        padded_data = padder.update(message) + padder.finalize()

        encrypted_bytes = encryptor.update(padded_data) + encryptor.finalize()
        encrypted_base64 = b64encode(encrypted_bytes).decode("utf-8")
        return encrypted_base64
    except Exception as e:
        print(e)
        return ""


def decrypt_with_aes(encrypted_message, key):
    try:
        iv = b"1234567890123456"
        key = key.encode("utf-8")

        # 解码 Base64 编码的加密消息
        encrypted_bytes = b64decode(encrypted_message)

        # 创建 AES 解密器
        cipher = Cipher(algorithms.AES(key), modes.CBC(iv), backend=default_backend())
        decryptor = cipher.decryptor()

        # 解密数据
        decrypted_padded_data = decryptor.update(encrypted_bytes) + decryptor.finalize()

        # 去除填充
        unpadder = padding.PKCS7(algorithms.AES.block_size).unpadder()
        decrypted_data = unpadder.update(decrypted_padded_data) + unpadder.finalize()

        # 返回解密后的字符串
        return decrypted_data.decode("utf-8")
    except Exception as e:
        print(e)
        return ""


def owner_check(env, searchKey='autoTest_01'):
    with open('data/config/token.yml', 'r') as f:
        config = yaml.safe_load(f)
    with open('data/config/config.yaml', 'r') as f2:
        url = yaml.safe_load(f2)

    url = url['environments'][env]['host'] + url['environments'][env]['owner_check']
    token = config['token']
    headers = {'Content-Type': 'application/json', 'version': '2.0', 'Authorization': token}
    query_params = {
        'page': '1',
        'size': '10',
        'filter': '{}',
        'searchKey': searchKey
    }
    payload = {
    }
    data = json.dumps(payload)
    try:
        # 发送 GET 请求
        response = requests.get(url, data=data, headers=headers, params=query_params)

        # 检查响应状态
        response.raise_for_status()  # 如果响应状态码不是 200，抛出异常

        # 解析 JSON 响应
        response_data = response.json()
        # print(response_data)

        # 提取 directory_id
        owner_id = response_data['data']['list'][0]['id']
        logging.info("成功----已提取到用户ID: %s", owner_id)
        return owner_id
    except requests.exceptions.RequestException as e:
        logging.error("失败----请求失败: %s", e)
    except json.JSONDecodeError:
        logging.error("失败----解析 JSON 响应失败")
